home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume2 / compress4.0 / part1 < prev    next >
Encoding:
Internet Message Format  |  1986-11-30  |  48.9 KB

  1. From: vax135!petsd!joe (Joe Orost)
  2. Subject: Compress 4.0 (part 1 of 2)
  3. Newsgroups: mod.sources
  4. Approved: john@genrad.UUCP
  5.  
  6. Mod.sources:  Volume 2, Issue 28
  7. Submitted by: vax135!petsd!joe (Joe Orost)
  8.  
  9. #! /bin/sh
  10. # This is a shell archive, meaning:
  11. # 1. Remove everything above the #! /bin/sh line.
  12. # 2. Save the resulting text in a file.
  13. # 3. Execute the file with /bin/sh (not csh) to create the files:
  14. #    compress.1
  15. #    compress.c
  16. #    Makefile
  17. #    usermem
  18. # This archive created: Thu Aug  1 11:51:23 1985
  19. export PATH; PATH=/bin:$PATH
  20. echo shar: extracting "'compress.1'" '(5147 characters)'
  21. if test -f 'compress.1'
  22. then
  23.     echo shar: will not over-write existing file "'compress.1'"
  24. else
  25. sed 's/^X//' << \SHAR_EOF > 'compress.1'
  26. X.PU
  27. X.TH COMPRESS 1 local
  28. X.SH NAME
  29. compress, uncompress, zcat \- compress and expand data
  30. X.SH SYNOPSIS
  31. X.ll +8
  32. X.B compress
  33. [
  34. X.B \-f
  35. ] [
  36. X.B \-v
  37. ] [
  38. X.B \-c
  39. ] [
  40. X.B \-V
  41. ] [
  42. X.B \-b
  43. X.I bits
  44. ] [
  45. X.I "name \&..."
  46. ]
  47. X.ll -8
  48. X.br
  49. X.B uncompress
  50. [
  51. X.B \-f
  52. ] [
  53. X.B \-v
  54. ] [
  55. X.B \-c
  56. ] [
  57. X.B \-V
  58. ] [
  59. X.I "name \&..."
  60. ]
  61. X.br
  62. X.B zcat
  63. [
  64. X.B \-V
  65. ] [
  66. X.I "name \&..."
  67. ]
  68. X.SH DESCRIPTION
  69. X.I Compress
  70. reduces the size of the named files using adaptive Lempel-Ziv coding.
  71. Whenever possible,
  72. each file is replaced by one with the extension
  73. X.B "\&.Z,"
  74. while keeping the same ownership modes, access and modification times.
  75. If no files are specified, the standard input is compressed to the
  76. standard output.
  77. Compressed files can be restored to their original form using
  78. X.I uncompress
  79. or
  80. X.I zcat.
  81. X.PP
  82. The
  83. X.B \-f
  84. option will force compression of
  85. X.I name.
  86. This is useful for compressing an entire directory,
  87. even if some of the files do not actually shrink.
  88. If
  89. X.B \-f
  90. is not given and
  91. X.I compress
  92. is run in the foreground,
  93. the user is prompted as to whether an existing file should be overwritten.
  94. X.PP
  95. The
  96. X.B \-c
  97. option makes
  98. X.I compress/uncompress
  99. write to the standard output; no files are changed.
  100. The nondestructive behavior of
  101. X.I zcat
  102. is identical to that of
  103. X.I uncompress
  104. X.B \-c.
  105. X.PP
  106. X.I Compress
  107. uses the modified Lempel-Ziv algorithm popularized in
  108. "A Technique for High Performance Data Compression",
  109. Terry A. Welch,
  110. X.I "IEEE Computer,"
  111. vol. 17, no. 6 (June 1984), pp. 8-19.
  112. Common substrings in the file are first replaced by 9-bit codes 257 and up.
  113. When code 512 is reached, the algorithm switches to 10-bit codes and
  114. continues to use more bits until the
  115. limit specified by the
  116. X.B \-b
  117. flag is reached (default 16).
  118. X.I Bits
  119. must be between 9 and 16.  The default can be changed in the source to allow
  120. X.I compress
  121. to be run on a smaller machine.
  122. X.PP
  123. After the
  124. X.I bits
  125. limit is attained,
  126. X.I compress
  127. periodically checks the compression ratio.  If it is increasing,
  128. X.I compress
  129. continues to use the existing code dictionary.  However,
  130. if the compression ratio decreases,
  131. X.I compress
  132. discards the table of substrings and rebuilds it from scratch.  This allows
  133. the algorithm to adapt to the next "block" of the file.
  134. X.PP
  135. Note that the
  136. X.B \-b
  137. flag is omitted for
  138. X.I uncompress,
  139. since the 
  140. X.I bits
  141. parameter specified during compression
  142. is encoded within the output, along with
  143. a magic number to ensure that neither decompression of random data nor
  144. recompression of compressed data is attempted. 
  145. X.PP
  146. X.ne 8
  147. The amount of compression obtained depends on the size of the
  148. input, the number of
  149. X.I bits
  150. per code, and the distribution of common substrings.
  151. Typically, text such as source code or English
  152. is reduced by 50\-60%.
  153. Compression is generally much better than that achieved by
  154. Huffman coding (as used in
  155. X.IR pack ),
  156. or adaptive Huffman coding
  157. X.RI ( compact ),
  158. and takes less time to compute.
  159. X.PP
  160. Under the
  161. X.B \-v
  162. option,
  163. a message is printed yielding the percentage of
  164. reduction for each file compressed.
  165. X.PP
  166. If the
  167. X.B \-V
  168. option is specified, the current version and compile options are printed on
  169. stderr.
  170. X.PP
  171. Exit status is normally 0;
  172. if the last file is larger after (attempted) compression, the status is 2;
  173. if an error occurs, exit status is 1.
  174. X.SH "SEE ALSO"
  175. pack(1), compact(1)
  176. X.SH "DIAGNOSTICS"
  177. Usage: compress [\-dfvcV] [\-b maxbits] [file ...]
  178. X.in +8
  179. Invalid options were specified on the command line.
  180. X.in -8
  181. Missing maxbits
  182. X.in +8
  183. Maxbits must follow
  184. X.BR \-b \.
  185. X.in -8
  186. X.IR file :
  187. not in compressed format
  188. X.in +8
  189. The file specified to
  190. X.I uncompress
  191. has not been compressed.
  192. X.in -8
  193. X.IR file :
  194. compressed with 
  195. X.I xx
  196. bits, can only handle 
  197. X.I yy
  198. bits
  199. X.in +8
  200. X.I File
  201. was compressed by a program that could deal with
  202. more 
  203. X.I bits
  204. than the compress code on this machine.
  205. Recompress the file with smaller
  206. X.IR bits \.
  207. X.in -8
  208. X.IR file :
  209. already has .Z suffix -- no change
  210. X.in +8
  211. The file is assumed to be already compressed.
  212. Rename the file and try again.
  213. X.in -8
  214. X.IR file :
  215. filename too long to tack on .Z
  216. X.in +8
  217. The file cannot be compressed because its name is longer than
  218. 12 characters.
  219. Rename and try again.
  220. This message does not occur on BSD systems.
  221. X.in -8
  222. X.I file
  223. already exists; do you wish to overwrite (y or n)?
  224. X.in +8
  225. Respond "y" if you want the output file to be replaced; "n" if not.
  226. X.in -8
  227. uncompress: corrupt input
  228. X.in +8
  229. A SIGSEGV violation was detected which usually means that the input file has
  230. been corrupted.
  231. X.in -8
  232. Compression: 
  233. X.I "xx.xx%"
  234. X.in +8
  235. Percentage of the input saved by compression.
  236. (Relevant only for
  237. X.BR \-v \.)
  238. X.in -8
  239. -- not a regular file: unchanged
  240. X.in +8
  241. When the input file is not a regular file,
  242. (e.g. a directory), it is
  243. left unaltered.
  244. X.in -8
  245. -- has 
  246. X.I xx 
  247. other links: unchanged
  248. X.in +8
  249. The input file has links; it is left unchanged.  See
  250. X.IR ln "(1)"
  251. for more information.
  252. X.in -8
  253. -- file unchanged
  254. X.in +8
  255. No savings is achieved by
  256. compression.  The input remains virgin.
  257. X.in -8
  258. X.SH "BUGS"
  259. Although compressed files are compatible between machines with large memory,
  260. X.BR \-b \12
  261. should be used for file transfer to architectures with 
  262. a small process data space (64KB or less, as exhibited by the DEC PDP
  263. series, the Intel 80286, etc.)
  264. SHAR_EOF
  265. if test 5147 -ne "`wc -c < 'compress.1'`"
  266. then
  267.     echo shar: error transmitting "'compress.1'" '(should have been 5147 characters)'
  268. fi
  269. fi # end of overwriting check
  270. echo shar: extracting "'compress.c'" '(39614 characters)'
  271. if test -f 'compress.c'
  272. then
  273.     echo shar: will not over-write existing file "'compress.c'"
  274. else
  275. sed 's/^X//' << \SHAR_EOF > 'compress.c'
  276. /* 
  277.  * Compress - data compression program 
  278.  */
  279. #define    min(a,b)    ((a>b) ? b : a)
  280.  
  281. /*
  282.  * machine variants which require cc -Dmachine:  pdp11, z8000, pcxt
  283.  */
  284.  
  285. /*
  286.  * Set USERMEM to the maximum amount of physical user memory available
  287.  * in bytes.  USERMEM is used to determine the maximum BITS that can be used
  288.  * for compression.
  289.  *
  290.  * SACREDMEM is the amount of physical memory saved for others; compress
  291.  * will hog the rest.
  292.  */
  293. #ifndef SACREDMEM
  294. #define SACREDMEM    0
  295. #endif
  296.  
  297. #ifndef USERMEM
  298. # define USERMEM     450000    /* default user memory */
  299. #endif
  300.  
  301. #ifdef interdata        /* (Perkin-Elmer) */
  302. #define SIGNED_COMPARE_SLOW    /* signed compare is slower than unsigned */
  303. #endif
  304.  
  305. #ifdef pdp11
  306. # define BITS     12    /* max bits/code for 16-bit machine */
  307. # define NO_UCHAR    /* also if "unsigned char" functions as signed char */
  308. # undef USERMEM 
  309. #endif /* pdp11 */    /* don't forget to compile with -i */
  310.  
  311. #ifdef z8000
  312. # define BITS     12
  313. # undef vax        /* weird preprocessor */
  314. # undef USERMEM 
  315. #endif /* z8000 */
  316.  
  317. #ifdef pcxt
  318. # define BITS   12
  319. # undef USERMEM
  320. #endif /* pcxt */
  321.  
  322. #ifdef USERMEM
  323. # if USERMEM >= (433484+SACREDMEM)
  324. #  define PBITS    16
  325. # else
  326. #  if USERMEM >= (229600+SACREDMEM)
  327. #   define PBITS    15
  328. #  else
  329. #   if USERMEM >= (127536+SACREDMEM)
  330. #    define PBITS    14
  331. #   else
  332. #    if USERMEM >= (73464+SACREDMEM)
  333. #     define PBITS    13
  334. #    else
  335. #     define PBITS    12
  336. #    endif
  337. #   endif
  338. #  endif
  339. # endif
  340. # undef USERMEM
  341. #endif /* USERMEM */
  342.  
  343. #ifdef PBITS        /* Preferred BITS for this memory size */
  344. # ifndef BITS
  345. #  define BITS PBITS
  346. # endif BITS
  347. #endif /* PBITS */
  348.  
  349. #if BITS == 16
  350. # define HSIZE    69001        /* 95% occupancy */
  351. #endif
  352. #if BITS == 15
  353. # define HSIZE    35023        /* 94% occupancy */
  354. #endif
  355. #if BITS == 14
  356. # define HSIZE    18013        /* 91% occupancy */
  357. #endif
  358. #if BITS == 13
  359. # define HSIZE    9001        /* 91% occupancy */
  360. #endif
  361. #if BITS <= 12
  362. # define HSIZE    5003        /* 80% occupancy */
  363. #endif
  364.  
  365. #ifdef M_XENIX            /* Stupid compiler can't handle arrays with */
  366. # if BITS == 16            /* more than 65535 bytes - so we fake it */
  367. #  define XENIX_16
  368. # else
  369. #  if BITS > 13            /* Code only handles BITS = 12, 13, or 16 */
  370. #   define BITS    13
  371. #  endif
  372. # endif
  373. #endif
  374.  
  375. /*
  376.  * a code_int must be able to hold 2**BITS values of type int, and also -1
  377.  */
  378. #if BITS > 15
  379. typedef long int    code_int;
  380. #else
  381. typedef int        code_int;
  382. #endif
  383.  
  384. #ifdef SIGNED_COMPARE_SLOW
  385. typedef unsigned long int count_int;
  386. typedef unsigned short int count_short;
  387. #else
  388. typedef long int      count_int;
  389. #endif
  390.  
  391. #ifdef NO_UCHAR
  392.  typedef char    char_type;
  393. #else
  394.  typedef    unsigned char    char_type;
  395. #endif /* UCHAR */
  396. char_type magic_header[] = { "\037\235" };    /* 1F 9D */
  397.  
  398. /* Defines for third byte of header */
  399. #define BIT_MASK    0x1f
  400. #define BLOCK_MASK    0x80
  401. /* Masks 0x40 and 0x20 are free.  I think 0x20 should mean that there is
  402.    a fourth header byte (for expansion).
  403. */
  404. #define INIT_BITS 9            /* initial number of bits/code */
  405.  
  406. /*
  407.  * compress.c - File compression ala IEEE Computer, June 1984.
  408.  *
  409.  * Authors:    Spencer W. Thomas    (decvax!harpo!utah-cs!utah-gr!thomas)
  410.  *        Jim McKie        (decvax!mcvax!jim)
  411.  *        Steve Davies        (decvax!vax135!petsd!peora!srd)
  412.  *        Ken Turkowski        (decvax!decwrl!turtlevax!ken)
  413.  *        James A. Woods        (decvax!ihnp4!ames!jaw)
  414.  *        Joe Orost        (decvax!vax135!petsd!joe)
  415.  *
  416.  * $Header: compress.c,v 4.0 85/07/30 12:50:00 joe Release $
  417.  * $Log:    compress.c,v $
  418.  * Revision 4.0  85/07/30  12:50:00  joe
  419.  * Removed ferror() calls in output routine on every output except first.
  420.  * Prepared for release to the world.
  421.  * 
  422.  * Revision 3.6  85/07/04  01:22:21  joe
  423.  * Remove much wasted storage by overlaying hash table with the tables
  424.  * used by decompress: tab_suffix[1<<BITS], stack[8000].  Updated USERMEM
  425.  * computations.  Fixed dump_tab() DEBUG routine.
  426.  *
  427.  * Revision 3.5  85/06/30  20:47:21  jaw
  428.  * Change hash function to use exclusive-or.  Rip out hash cache.  These
  429.  * speedups render the megamemory version defunct, for now.  Make decoder
  430.  * stack global.  Parts of the RCS trunks 2.7, 2.6, and 2.1 no longer apply.
  431.  *
  432.  * Revision 3.4  85/06/27  12:00:00  ken
  433.  * Get rid of all floating-point calculations by doing all compression ratio
  434.  * calculations in fixed point.
  435.  *
  436.  * Revision 3.3  85/06/24  21:53:24  joe
  437.  * Incorporate portability suggestion for M_XENIX.  Got rid of text on #else
  438.  * and #endif lines.  Cleaned up #ifdefs for vax and interdata.
  439.  *
  440.  * Revision 3.2  85/06/06  21:53:24  jaw
  441.  * Incorporate portability suggestions for Z8000, IBM PC/XT from mailing list.
  442.  * Default to "quiet" output (no compression statistics).
  443.  *
  444.  * Revision 3.1  85/05/12  18:56:13  jaw
  445.  * Integrate decompress() stack speedups (from early pointer mods by McKie).
  446.  * Repair multi-file USERMEM gaffe.  Unify 'force' flags to mimic semantics
  447.  * of SVR2 'pack'.  Streamline block-compress table clear logic.  Increase 
  448.  * output byte count by magic number size.
  449.  * 
  450.  * Revision 3.0   84/11/27  11:50:00  petsd!joe
  451.  * Set HSIZE depending on BITS.  Set BITS depending on USERMEM.  Unrolled
  452.  * loops in clear routines.  Added "-C" flag for 2.0 compatibility.  Used
  453.  * unsigned compares on Perkin-Elmer.  Fixed foreground check.
  454.  *
  455.  * Revision 2.7   84/11/16  19:35:39  ames!jaw
  456.  * Cache common hash codes based on input statistics; this improves
  457.  * performance for low-density raster images.  Pass on #ifdef bundle
  458.  * from Turkowski.
  459.  *
  460.  * Revision 2.6   84/11/05  19:18:21  ames!jaw
  461.  * Vary size of hash tables to reduce time for small files.
  462.  * Tune PDP-11 hash function.
  463.  *
  464.  * Revision 2.5   84/10/30  20:15:14  ames!jaw
  465.  * Junk chaining; replace with the simpler (and, on the VAX, faster)
  466.  * double hashing, discussed within.  Make block compression standard.
  467.  *
  468.  * Revision 2.4   84/10/16  11:11:11  ames!jaw
  469.  * Introduce adaptive reset for block compression, to boost the rate
  470.  * another several percent.  (See mailing list notes.)
  471.  *
  472.  * Revision 2.3   84/09/22  22:00:00  petsd!joe
  473.  * Implemented "-B" block compress.  Implemented REVERSE sorting of tab_next.
  474.  * Bug fix for last bits.  Changed fwrite to putchar loop everywhere.
  475.  *
  476.  * Revision 2.2   84/09/18  14:12:21  ames!jaw
  477.  * Fold in news changes, small machine typedef from thomas,
  478.  * #ifdef interdata from joe.
  479.  *
  480.  * Revision 2.1   84/09/10  12:34:56  ames!jaw
  481.  * Configured fast table lookup for 32-bit machines.
  482.  * This cuts user time in half for b <= FBITS, and is useful for news batching
  483.  * from VAX to PDP sites.  Also sped up decompress() [fwrite->putc] and
  484.  * added signal catcher [plus beef in writeerr()] to delete effluvia.
  485.  *
  486.  * Revision 2.0   84/08/28  22:00:00  petsd!joe
  487.  * Add check for foreground before prompting user.  Insert maxbits into
  488.  * compressed file.  Force file being uncompressed to end with ".Z".
  489.  * Added "-c" flag and "zcat".  Prepared for release.
  490.  *
  491.  * Revision 1.10  84/08/24  18:28:00  turtlevax!ken
  492.  * Will only compress regular files (no directories), added a magic number
  493.  * header (plus an undocumented -n flag to handle old files without headers),
  494.  * added -f flag to force overwriting of possibly existing destination file,
  495.  * otherwise the user is prompted for a response.  Will tack on a .Z to a
  496.  * filename if it doesn't have one when decompressing.  Will only replace
  497.  * file if it was compressed.
  498.  *
  499.  * Revision 1.9  84/08/16  17:28:00  turtlevax!ken
  500.  * Removed scanargs(), getopt(), added .Z extension and unlimited number of
  501.  * filenames to compress.  Flags may be clustered (-Ddvb12) or separated
  502.  * (-D -d -v -b 12), or combination thereof.  Modes and other status is
  503.  * copied with copystat().  -O bug for 4.2 seems to have disappeared with
  504.  * 1.8.
  505.  *
  506.  * Revision 1.8  84/08/09  23:15:00  joe
  507.  * Made it compatible with vax version, installed jim's fixes/enhancements
  508.  *
  509.  * Revision 1.6  84/08/01  22:08:00  joe
  510.  * Sped up algorithm significantly by sorting the compress chain.
  511.  *
  512.  * Revision 1.5  84/07/13  13:11:00  srd
  513.  * Added C version of vax asm routines.  Changed structure to arrays to
  514.  * save much memory.  Do unsigned compares where possible (faster on
  515.  * Perkin-Elmer)
  516.  *
  517.  * Revision 1.4  84/07/05  03:11:11  thomas
  518.  * Clean up the code a little and lint it.  (Lint complains about all
  519.  * the regs used in the asm, but I'm not going to "fix" this.)
  520.  *
  521.  * Revision 1.3  84/07/05  02:06:54  thomas
  522.  * Minor fixes.
  523.  *
  524.  * Revision 1.2  84/07/05  00:27:27  thomas
  525.  * Add variable bit length output.
  526.  *
  527.  */
  528. static char rcs_ident[] = "$Header: compress.c,v 4.0 85/07/30 12:50:00 joe Release $";
  529.  
  530. #include <stdio.h>
  531. #include <ctype.h>
  532. #include <signal.h>
  533. #include <sys/types.h>
  534. #include <sys/stat.h>
  535.  
  536. #define ARGVAL() (*++(*argv) || (--argc && *++argv))
  537.  
  538. int n_bits;                /* number of bits/code */
  539. int maxbits = BITS;            /* user settable max # bits/code */
  540. code_int maxcode;            /* maximum code, given n_bits */
  541. code_int maxmaxcode = 1 << BITS;    /* should NEVER generate this code */
  542. #ifdef COMPATIBLE        /* But wrong! */
  543. # define MAXCODE(n_bits)    (1 << (n_bits) - 1)
  544. #else
  545. # define MAXCODE(n_bits)    ((1 << (n_bits)) - 1)
  546. #endif /* COMPATIBLE */
  547.  
  548. #ifdef XENIX_16
  549. count_int htab0[8192];
  550. count_int htab1[8192];
  551. count_int htab2[8192];
  552. count_int htab3[8192];
  553. count_int htab4[8192];
  554. count_int htab5[8192];
  555. count_int htab6[8192];
  556. count_int htab7[8192];
  557. count_int htab8[HSIZE-65536];
  558. count_int * htab[9] = {
  559.     htab0, htab1, htab2, htab3, htab4, htab5, htab6, htab7, htab8 };
  560.  
  561. #define htabof(i)    (htab[(i) >> 13][(i) & 0x1fff])
  562. unsigned short code0tab[16384];
  563. unsigned short code1tab[16384];
  564. unsigned short code2tab[16384];
  565. unsigned short code3tab[16384];
  566. unsigned short code4tab[16384];
  567. unsigned short * codetab[5] = {
  568.     code0tab, code1tab, code2tab, code3tab, code4tab };
  569.  
  570. #define codetabof(i)    (codetab[(i) >> 14][(i) & 0x3fff])
  571.  
  572. #else    /* Normal machine */
  573. count_int htab [HSIZE];
  574. unsigned short codetab [HSIZE];
  575. #define htabof(i)    htab[i]
  576. #define codetabof(i)    codetab[i]
  577. #endif    /* XENIX_16 */
  578. code_int hsize = HSIZE;            /* for dynamic table sizing */
  579. count_int fsize;
  580.  
  581. /*
  582.  * To save much memory, we overlay the table used by compress() with those
  583.  * used by decompress().  The tab_prefix table is the same size and type
  584.  * as the codetab.  The tab_suffix table needs 2**BITS characters.  We
  585.  * get this from the beginning of htab.  The output stack uses the rest
  586.  * of htab, and contains characters.  There is plenty of room for any
  587.  * possible stack (stack used to be 8000 characters).
  588.  */
  589.  
  590. #define tab_prefixof(i)    codetabof(i)
  591. #ifdef XENIX_16
  592. # define tab_suffixof(i)    ((char_type *)htab[(i)>>15])[(i) & 0x7fff]
  593. # define de_stack        ((char_type *)(htab2))
  594. #else    /* Normal machine */
  595. # define tab_suffixof(i)    ((char_type *)(htab))[i]
  596. # define de_stack        ((char_type *)&tab_suffixof(1<<BITS))
  597. #endif    /* XENIX_16 */
  598.  
  599. code_int free_ent = 0;            /* first unused entry */
  600. int exit_stat = 0;
  601.  
  602. code_int getcode();
  603.  
  604. Usage() {
  605. #ifdef DEBUG
  606. fprintf(stderr,"Usage: compress [-dDVfc] [-b maxbits] [file ...]\n");
  607. }
  608. int debug = 0;
  609. #else
  610. fprintf(stderr,"Usage: compress [-dfvcV] [-b maxbits] [file ...]\n");
  611. }
  612. #endif /* DEBUG */
  613. int nomagic = 0;    /* Use a 3-byte magic number header, unless old file */
  614. int zcat_flg = 0;    /* Write output on stdout, suppress messages */
  615. int quiet = 1;        /* don't tell me about compression */
  616.  
  617. /*
  618.  * block compression parameters -- after all codes are used up,
  619.  * and compression rate changes, start over.
  620.  */
  621. int block_compress = BLOCK_MASK;
  622. int clear_flg = 0;
  623. long int ratio = 0;
  624. #define CHECK_GAP 10000    /* ratio check interval */
  625. count_int checkpoint = CHECK_GAP;
  626. /*
  627.  * the next two codes should not be changed lightly, as they must not
  628.  * lie within the contiguous general code space.
  629.  */ 
  630. #define FIRST    257    /* first free entry */
  631. #define    CLEAR    256    /* table clear output code */
  632.  
  633. int force = 0;
  634. char ofname [100];
  635. #ifdef DEBUG
  636. int verbose = 0;
  637. #endif /* DEBUG */
  638. int (*bgnd_flag)();
  639.  
  640. int do_decomp = 0;
  641.  
  642. /*****************************************************************
  643.  * TAG( main )
  644.  *
  645.  * Algorithm from "A Technique for High Performance Data Compression",
  646.  * Terry A. Welch, IEEE Computer Vol 17, No 6 (June 1984), pp 8-19.
  647.  *
  648.  * Usage: compress [-dfvc] [-b bits] [file ...]
  649.  * Inputs:
  650.  *    -d:        If given, decompression is done instead.
  651.  *
  652.  *      -c:         Write output on stdout, don't remove original.
  653.  *
  654.  *      -b:         Parameter limits the max number of bits/code.
  655.  *
  656.  *    -f:        Forces output file to be generated, even if one already
  657.  *            exists, and even if no space is saved by compressing.
  658.  *            If -f is not used, the user will be prompted if stdin is
  659.  *            a tty, otherwise, the output file will not be overwritten.
  660.  *
  661.  *      -v:        Write compression statistics
  662.  *
  663.  *     file ...:   Files to be compressed.  If none specified, stdin
  664.  *            is used.
  665.  * Outputs:
  666.  *    file.Z:        Compressed form of file with same mode, owner, and utimes
  667.  *     or stdout   (if stdin used as input)
  668.  *
  669.  * Assumptions:
  670.  *    When filenames are given, replaces with the compressed version
  671.  *    (.Z suffix) only if the file decreases in size.
  672.  * Algorithm:
  673.  *     Modified Lempel-Ziv method (LZW).  Basically finds common
  674.  * substrings and replaces them with a variable size code.  This is
  675.  * deterministic, and can be done on the fly.  Thus, the decompression
  676.  * procedure needs no input table, but tracks the way the table was built.
  677.  */
  678.  
  679. main( argc, argv )
  680. register int argc; char **argv;
  681. {
  682.     int overwrite = 0;    /* Do not overwrite unless given -f flag */
  683.     char tempname[100];
  684.     char **filelist, **fileptr;
  685.     char *cp, *rindex(), *malloc();
  686.     struct stat statbuf;
  687.     extern onintr(), oops();
  688.  
  689.  
  690.     if ( (bgnd_flag = signal ( SIGINT, SIG_IGN )) != SIG_IGN ) {
  691.     signal ( SIGINT, onintr );
  692.     signal ( SIGSEGV, oops );
  693.     }
  694.  
  695. #ifdef COMPATIBLE
  696.     nomagic = 1;    /* Original didn't have a magic number */
  697. #endif /* COMPATIBLE */
  698.  
  699.     filelist = fileptr = (char **)(malloc(argc * sizeof(*argv)));
  700.     *filelist = NULL;
  701.  
  702.     if((cp = rindex(argv[0], '/')) != 0) {
  703.     cp++;
  704.     } else {
  705.     cp = argv[0];
  706.     }
  707.     if(strcmp(cp, "uncompress") == 0) {
  708.     do_decomp = 1;
  709.     } else if(strcmp(cp, "zcat") == 0) {
  710.     do_decomp = 1;
  711.     zcat_flg = 1;
  712.     }
  713.  
  714. #ifdef BSD4_2
  715.     /* 4.2BSD dependent - take it out if not */
  716.     setlinebuf( stderr );
  717. #endif /* BSD4_2 */
  718.  
  719.     /* Argument Processing
  720.      * All flags are optional.
  721.      * -D => debug
  722.      * -V => print Version; debug verbose
  723.      * -d => do_decomp
  724.      * -v => unquiet
  725.      * -f => force overwrite of output file
  726.      * -n => no header: useful to uncompress old files
  727.      * -b maxbits => maxbits.  If -b is specified, then maxbits MUST be
  728.      *        given also.
  729.      * -c => cat all output to stdout
  730.      * -C => generate output compatible with compress 2.0.
  731.      * if a string is left, must be an input filename.
  732.      */
  733.     for (argc--, argv++; argc > 0; argc--, argv++) {
  734.     if (**argv == '-') {    /* A flag argument */
  735.         while (*++(*argv)) {    /* Process all flags in this arg */
  736.         switch (**argv) {
  737. #ifdef DEBUG
  738.             case 'D':
  739.             debug = 1;
  740.             break;
  741.             case 'V':
  742.             verbose = 1;
  743.             version();
  744.             break;
  745. #else
  746.             case 'V':
  747.             version();
  748.             break;
  749. #endif /* DEBUG */
  750.             case 'v':
  751.             quiet = 0;
  752.             break;
  753.             case 'd':
  754.             do_decomp = 1;
  755.             break;
  756.             case 'f':
  757.             case 'F':
  758.             overwrite = 1;
  759.             force = 1;
  760.             break;
  761.             case 'n':
  762.             nomagic = 1;
  763.             break;
  764.             case 'C':
  765.             block_compress = 0;
  766.             break;
  767.             case 'b':
  768.             if (!ARGVAL()) {
  769.                 fprintf(stderr, "Missing maxbits\n");
  770.                 Usage();
  771.                 exit(1);
  772.             }
  773.             maxbits = atoi(*argv);
  774.             goto nextarg;
  775.             case 'c':
  776.             zcat_flg = 1;
  777.             break;
  778.             case 'q':
  779.             quiet = 1;
  780.             break;
  781.             default:
  782.             fprintf(stderr, "Unknown flag: '%c'; ", **argv);
  783.             Usage();
  784.             exit(1);
  785.         }
  786.         }
  787.     }
  788.     else {        /* Input file name */
  789.         *fileptr++ = *argv;    /* Build input file list */
  790.         *fileptr = NULL;
  791.         /* process nextarg; */
  792.     }
  793.     nextarg: continue;
  794.     }
  795.  
  796.     if(maxbits < INIT_BITS) maxbits = INIT_BITS;
  797.     if (maxbits > BITS) maxbits = BITS;
  798.     maxmaxcode = 1 << maxbits;
  799.  
  800.     if (*filelist != NULL) {
  801.     for (fileptr = filelist; *fileptr; fileptr++) {
  802.         exit_stat = 0;
  803.         if (do_decomp != 0) {            /* DECOMPRESSION */
  804.         /* Check for .Z suffix */
  805.         if (strcmp(*fileptr + strlen(*fileptr) - 2, ".Z") != 0) {
  806.             /* No .Z: tack one on */
  807.             strcpy(tempname, *fileptr);
  808.             strcat(tempname, ".Z");
  809.             *fileptr = tempname;
  810.         }
  811.         /* Open input file */
  812.         if ((freopen(*fileptr, "r", stdin)) == NULL) {
  813.             perror(*fileptr); continue;
  814.         }
  815.         /* Check the magic number */
  816.         if (nomagic == 0) {
  817.             if ((getchar() != (magic_header[0] & 0xFF))
  818.              || (getchar() != (magic_header[1] & 0xFF))) {
  819.             fprintf(stderr, "%s: not in compressed format\n",
  820.                 *fileptr);
  821.             continue;
  822.             }
  823.             maxbits = getchar();    /* set -b from file */
  824.             block_compress = maxbits & BLOCK_MASK;
  825.             maxbits &= BIT_MASK;
  826.             maxmaxcode = 1 << maxbits;
  827.             if(maxbits > BITS) {
  828.             fprintf(stderr,
  829.             "%s: compressed with %d bits, can only handle %d bits\n",
  830.             *fileptr, maxbits, BITS);
  831.             continue;
  832.             }
  833.         }
  834.         /* Generate output filename */
  835.         strcpy(ofname, *fileptr);
  836.         ofname[strlen(*fileptr) - 2] = '\0';  /* Strip off .Z */
  837.         } else {                    /* COMPRESSION */
  838.         if (strcmp(*fileptr + strlen(*fileptr) - 2, ".Z") == 0) {
  839.                 fprintf(stderr, "%s: already has .Z suffix -- no change\n",
  840.                 *fileptr);
  841.             continue;
  842.         }
  843.         /* Open input file */
  844.         if ((freopen(*fileptr, "r", stdin)) == NULL) {
  845.             perror(*fileptr); continue;
  846.         }
  847.         stat ( *fileptr, &statbuf );
  848.         fsize = (long) statbuf.st_size;
  849.         /*
  850.          * tune hash table size for small files -- ad hoc,
  851.          * but the sizes match earlier #defines, which
  852.          * serve as upper bounds on the number of output codes. 
  853.          */
  854.         hsize = HSIZE;
  855.         if ( fsize < (1 << 12) )
  856.             hsize = min ( 5003, HSIZE );
  857.         else if ( fsize < (1 << 13) )
  858.             hsize = min ( 9001, HSIZE );
  859.         else if ( fsize < (1 << 14) )
  860.             hsize = min ( 18013, HSIZE );
  861.         else if ( fsize < (1 << 15) )
  862.             hsize = min ( 35023, HSIZE );
  863.         else if ( fsize < 47000 )
  864.             hsize = min ( 50021, HSIZE );
  865.  
  866.         /* Generate output filename */
  867.         strcpy(ofname, *fileptr);
  868. #ifndef BSD4_2        /* Short filenames */
  869.         if ((cp=rindex(ofname,'/')) != NULL)    cp++;
  870.         else                    cp = ofname;
  871.         if (strlen(cp) > 12) {
  872.             fprintf(stderr,"%s: filename too long to tack on .Z\n",cp);
  873.             continue;
  874.         }
  875. #endif  /* BSD4_2        Long filenames allowed */
  876.         strcat(ofname, ".Z");
  877.         }
  878.         /* Check for overwrite of existing file */
  879.         if (overwrite == 0 && zcat_flg == 0) {
  880.         if (stat(ofname, &statbuf) == 0) {
  881.             char response[2];
  882.             response[0] = 'n';
  883.             fprintf(stderr, "%s already exists;", ofname);
  884.             if (foreground()) {
  885.             fprintf(stderr, " do you wish to overwrite %s (y or n)? ",
  886.             ofname);
  887.             fflush(stderr);
  888.             read(2, response, 2);
  889.             while (response[1] != '\n') {
  890.                 if (read(2, response+1, 1) < 0) {    /* Ack! */
  891.                 perror("stderr"); break;
  892.                 }
  893.             }
  894.             }
  895.             if (response[0] != 'y') {
  896.             fprintf(stderr, "\tnot overwritten\n");
  897.             continue;
  898.             }
  899.         }
  900.         }
  901.         if(zcat_flg == 0) {        /* Open output file */
  902.         if (freopen(ofname, "w", stdout) == NULL) {
  903.             perror(ofname);
  904.             continue;
  905.         }
  906.         if(!quiet)
  907.             fprintf(stderr, "%s: ", *fileptr);
  908.         }
  909.  
  910.         /* Actually do the compression/decompression */
  911.         if (do_decomp == 0)    compress();
  912. #ifndef DEBUG
  913.         else            decompress();
  914. #else
  915.         else if (debug == 0)    decompress();
  916.         else            printcodes();
  917.         if (verbose)        dump_tab();
  918. #endif /* DEBUG */
  919.         if(zcat_flg == 0) {
  920.         copystat(*fileptr, ofname);    /* Copy stats */
  921.         if((exit_stat == 1) || (!quiet))
  922.             putc('\n', stderr);
  923.         }
  924.     }
  925.     } else {        /* Standard input */
  926.     if (do_decomp == 0) {
  927.         compress();
  928. #ifdef DEBUG
  929.         if(verbose)        dump_tab();
  930. #endif /* DEBUG */
  931.         if(!quiet)
  932.             putc('\n', stderr);
  933.     } else {
  934.         /* Check the magic number */
  935.         if (nomagic == 0) {
  936.         if ((getchar()!=(magic_header[0] & 0xFF))
  937.          || (getchar()!=(magic_header[1] & 0xFF))) {
  938.             fprintf(stderr, "stdin: not in compressed format\n");
  939.             exit(1);
  940.         }
  941.         maxbits = getchar();    /* set -b from file */
  942.         block_compress = maxbits & BLOCK_MASK;
  943.         maxbits &= BIT_MASK;
  944.         maxmaxcode = 1 << maxbits;
  945.         fsize = 100000;        /* assume stdin large for USERMEM */
  946.         if(maxbits > BITS) {
  947.             fprintf(stderr,
  948.             "stdin: compressed with %d bits, can only handle %d bits\n",
  949.             maxbits, BITS);
  950.             exit(1);
  951.         }
  952.         }
  953. #ifndef DEBUG
  954.         decompress();
  955. #else
  956.         if (debug == 0)    decompress();
  957.         else        printcodes();
  958.         if (verbose)    dump_tab();
  959. #endif /* DEBUG */
  960.     }
  961.     }
  962.     exit(exit_stat);
  963. }
  964.  
  965. static int offset;
  966. long int in_count = 1;            /* length of input */
  967. long int bytes_out;            /* length of compressed output */
  968. long int out_count = 0;            /* # of codes output (for debugging) */
  969.  
  970. /*
  971.  * compress stdin to stdout
  972.  *
  973.  * Algorithm:  use open addressing double hashing (no chaining) on the 
  974.  * prefix code / next character combination.  We do a variant of Knuth's
  975.  * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
  976.  * secondary probe.  Here, the modular division first probe is gives way
  977.  * to a faster exclusive-or manipulation.  Also do block compression with
  978.  * an adaptive reset, whereby the code table is cleared when the compression
  979.  * ratio decreases, but after the table fills.  The variable-length output
  980.  * codes are re-sized at this point, and a special CLEAR code is generated
  981.  * for the decompressor.  Late addition:  construct the table according to
  982.  * file size for noticeable speed improvement on small files.  Please direct
  983.  * questions about this implementation to ames!jaw.
  984.  */
  985.  
  986. compress() {
  987.     register long fcode;
  988.     register code_int i = 0;
  989.     register int c;
  990.     register code_int ent;
  991. #ifdef XENIX_16
  992.     register code_int disp;
  993. #else    /* Normal machine */
  994.     register int disp;
  995. #endif
  996.     register code_int hsize_reg;
  997.     register int hshift;
  998.  
  999. #ifndef COMPATIBLE
  1000.     if (nomagic == 0) {
  1001.     putchar(magic_header[0]); putchar(magic_header[1]);
  1002.     putchar((char)(maxbits | block_compress));
  1003.     if(ferror(stdout))
  1004.         writeerr();
  1005.     }
  1006. #endif /* COMPATIBLE */
  1007.  
  1008.     offset = 0;
  1009.     bytes_out = 3;        /* includes 3-byte header mojo */
  1010.     out_count = 0;
  1011.     clear_flg = 0;
  1012.     ratio = 0;
  1013.     in_count = 1;
  1014.     checkpoint = CHECK_GAP;
  1015.     maxcode = MAXCODE(n_bits = INIT_BITS);
  1016.     free_ent = ((block_compress) ? FIRST : 256 );
  1017.  
  1018.     ent = getchar ();
  1019.  
  1020.     hshift = 0;
  1021.     for ( fcode = (long) hsize;  fcode < 65536L; fcode *= 2L )
  1022.         hshift++;
  1023.     hshift = 8 - hshift;        /* set hash code range bound */
  1024.  
  1025.     hsize_reg = hsize;
  1026.     cl_hash( (count_int) hsize_reg);        /* clear hash table */
  1027.  
  1028. #ifdef SIGNED_COMPARE_SLOW
  1029.     while ( (c = getchar()) != (unsigned) EOF ) {
  1030. #else
  1031.     while ( (c = getchar()) != EOF ) {
  1032. #endif
  1033.     in_count++;
  1034.     fcode = (long) (((long) c << maxbits) + ent);
  1035.      i = ((c << hshift) ^ ent);    /* xor hashing */
  1036.  
  1037.     if ( htabof (i) == fcode ) {
  1038.         ent = codetabof (i);
  1039.         continue;
  1040.     } else if ( (long)htabof (i) < 0 )    /* empty slot */
  1041.         goto nomatch;
  1042.      disp = hsize_reg - i;        /* secondary hash (after G. Knott) */
  1043.     if ( i == 0 )
  1044.         disp = 1;
  1045. probe:
  1046.     if ( (i -= disp) < 0 )
  1047.         i += hsize_reg;
  1048.  
  1049.     if ( htabof (i) == fcode ) {
  1050.         ent = codetabof (i);
  1051.         continue;
  1052.     }
  1053.     if ( (long)htabof (i) > 0 ) 
  1054.         goto probe;
  1055. nomatch:
  1056.     output ( (code_int) ent );
  1057.     out_count++;
  1058.      ent = c;
  1059. #ifdef SIGNED_COMPARE_SLOW
  1060.     if ( (unsigned) free_ent < (unsigned) maxmaxcode) {
  1061. #else
  1062.     if ( free_ent < maxmaxcode ) {
  1063. #endif
  1064.          codetabof (i) = free_ent++;    /* code -> hashtable */
  1065.         htabof (i) = fcode;
  1066.     }
  1067.     else if ( (count_int)in_count >= checkpoint && block_compress )
  1068.         cl_block ();
  1069.     }
  1070.     /*
  1071.      * Put out the final code.
  1072.      */
  1073.     output( (code_int)ent );
  1074.     out_count++;
  1075.     output( (code_int)-1 );
  1076.  
  1077.     /*
  1078.      * Print out stats on stderr
  1079.      */
  1080.     if(zcat_flg == 0 && !quiet) {
  1081. #ifdef DEBUG
  1082.     fprintf( stderr,
  1083.         "%ld chars in, %ld codes (%ld bytes) out, compression factor: ",
  1084.         in_count, out_count, bytes_out );
  1085.     prratio( stderr, in_count, bytes_out );
  1086.     fprintf( stderr, "\n");
  1087.     fprintf( stderr, "\tCompression as in compact: " );
  1088.     prratio( stderr, in_count-bytes_out, in_count );
  1089.     fprintf( stderr, "\n");
  1090.     fprintf( stderr, "\tLargest code (of last block) was %d (%d bits)\n",
  1091.         free_ent - 1, n_bits );
  1092. #else /* !DEBUG */
  1093.     fprintf( stderr, "Compression: " );
  1094.     prratio( stderr, in_count-bytes_out, in_count );
  1095. #endif /* DEBUG */
  1096.     }
  1097.     if(bytes_out > in_count)    /* exit(2) if no savings */
  1098.     exit_stat = 2;
  1099.     return;
  1100. }
  1101.  
  1102. /*****************************************************************
  1103.  * TAG( output )
  1104.  *
  1105.  * Output the given code.
  1106.  * Inputs:
  1107.  *     code:    A n_bits-bit integer.  If == -1, then EOF.  This assumes
  1108.  *        that n_bits =< (long)wordsize - 1.
  1109.  * Outputs:
  1110.  *     Outputs code to the file.
  1111.  * Assumptions:
  1112.  *    Chars are 8 bits long.
  1113.  * Algorithm:
  1114.  *     Maintain a BITS character long buffer (so that 8 codes will
  1115.  * fit in it exactly).  Use the VAX insv instruction to insert each
  1116.  * code in turn.  When the buffer fills up empty it and start over.
  1117.  */
  1118.  
  1119. static char buf[BITS];
  1120.  
  1121. #ifndef vax
  1122. char_type lmask[9] = {0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00};
  1123. char_type rmask[9] = {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
  1124. #endif /* vax */
  1125.  
  1126. output( code )
  1127. code_int  code;
  1128. {
  1129. #ifdef DEBUG
  1130.     static int col = 0;
  1131. #endif /* DEBUG */
  1132.  
  1133.     /*
  1134.      * On the VAX, it is important to have the register declarations
  1135.      * in exactly the order given, or the asm will break.
  1136.      */
  1137.     register int r_off = offset, bits= n_bits;
  1138.     register char * bp = buf;
  1139.  
  1140. #ifdef DEBUG
  1141.     if ( verbose )
  1142.         fprintf( stderr, "%5d%c", code,
  1143.             (col+=6) >= 74 ? (col = 0, '\n') : ' ' );
  1144. #endif /* DEBUG */
  1145.     if ( code >= 0 ) {
  1146. #ifdef vax
  1147.     /* VAX DEPENDENT!! Implementation on other machines is below.
  1148.      *
  1149.      * Translation: Insert BITS bits from the argument starting at
  1150.      * offset bits from the beginning of buf.
  1151.      */
  1152.     0;    /* Work around for pcc -O bug with asm and if stmt */
  1153.     asm( "insv    4(ap),r11,r10,(r9)" );
  1154. #else /* not a vax */
  1155. /* 
  1156.  * byte/bit numbering on the VAX is simulated by the following code
  1157.  */
  1158.     /*
  1159.      * Get to the first byte.
  1160.      */
  1161.     bp += (r_off >> 3);
  1162.     r_off &= 7;
  1163.     /*
  1164.      * Since code is always >= 8 bits, only need to mask the first
  1165.      * hunk on the left.
  1166.      */
  1167.     *bp = (*bp & rmask[r_off]) | (code << r_off) & lmask[r_off];
  1168.     bp++;
  1169.     bits -= (8 - r_off);
  1170.     code >>= 8 - r_off;
  1171.     /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
  1172.     if ( bits >= 8 ) {
  1173.         *bp++ = code;
  1174.         code >>= 8;
  1175.         bits -= 8;
  1176.     }
  1177.     /* Last bits. */
  1178.     if(bits)
  1179.         *bp = code;
  1180. #endif /* vax */
  1181.     offset += n_bits;
  1182.     if ( offset == (n_bits << 3) ) {
  1183.         bp = buf;
  1184.         bits = n_bits;
  1185.         bytes_out += bits;
  1186.         do
  1187.         putchar(*bp++);
  1188.         while(--bits);
  1189.         offset = 0;
  1190.     }
  1191.  
  1192.     /*
  1193.      * If the next entry is going to be too big for the code size,
  1194.      * then increase it, if possible.
  1195.      */
  1196.     if ( free_ent > maxcode || (clear_flg > 0))
  1197.     {
  1198.         /*
  1199.          * Write the whole buffer, because the input side won't
  1200.          * discover the size increase until after it has read it.
  1201.          */
  1202.         if ( offset > 0 ) {
  1203.         if( fwrite( buf, 1, n_bits, stdout ) != n_bits)
  1204.             writeerr();
  1205.         bytes_out += n_bits;
  1206.         }
  1207.         offset = 0;
  1208.  
  1209.         if ( clear_flg ) {
  1210.                 maxcode = MAXCODE (n_bits = INIT_BITS);
  1211.             clear_flg = 0;
  1212.         }
  1213.         else {
  1214.             n_bits++;
  1215.             if ( n_bits == maxbits )
  1216.             maxcode = maxmaxcode;
  1217.             else
  1218.             maxcode = MAXCODE(n_bits);
  1219.         }
  1220. #ifdef DEBUG
  1221.         if ( debug ) {
  1222.         fprintf( stderr, "\nChange to %d bits\n", n_bits );
  1223.         col = 0;
  1224.         }
  1225. #endif /* DEBUG */
  1226.     }
  1227.     } else {
  1228.     /*
  1229.      * At EOF, write the rest of the buffer.
  1230.      */
  1231.     if ( offset > 0 )
  1232.         fwrite( buf, 1, (offset + 7) / 8, stdout );
  1233.     bytes_out += (offset + 7) / 8;
  1234.     offset = 0;
  1235.     fflush( stdout );
  1236. #ifdef DEBUG
  1237.     if ( verbose )
  1238.         fprintf( stderr, "\n" );
  1239. #endif /* DEBUG */
  1240.     if( ferror( stdout ) )
  1241.         writeerr();
  1242.     }
  1243. }
  1244.  
  1245. /*
  1246.  * Decompress stdin to stdout.  This routine adapts to the codes in the
  1247.  * file building the "string" table on-the-fly; requiring no table to
  1248.  * be stored in the compressed file.  The tables used herein are shared
  1249.  * with those of the compress() routine.  See the definitions above.
  1250.  */
  1251.  
  1252. decompress() {
  1253.     register char_type *stackp;
  1254.     register int finchar;
  1255.     register code_int code, oldcode, incode;
  1256.  
  1257.     /*
  1258.      * As above, initialize the first 256 entries in the table.
  1259.      */
  1260.     maxcode = MAXCODE(n_bits = INIT_BITS);
  1261.     for ( code = 255; code >= 0; code-- ) {
  1262.     tab_prefixof(code) = 0;
  1263.     tab_suffixof(code) = (char_type)code;
  1264.     }
  1265.     free_ent = ((block_compress) ? FIRST : 256 );
  1266.  
  1267.     finchar = oldcode = getcode();
  1268.     if(oldcode == -1)    /* EOF already? */
  1269.     return;            /* Get out of here */
  1270.     putchar( (char)finchar );        /* first code must be 8 bits = char */
  1271.     if(ferror(stdout))        /* Crash if can't write */
  1272.     writeerr();
  1273.     stackp = de_stack;
  1274.  
  1275.     while ( (code = getcode()) > -1 ) {
  1276.  
  1277.     if ( (code == CLEAR) && block_compress ) {
  1278.         for ( code = 255; code >= 0; code-- )
  1279.         tab_prefixof(code) = 0;
  1280.         clear_flg = 1;
  1281.         free_ent = FIRST - 1;
  1282.         if ( (code = getcode ()) == -1 )    /* O, untimely death! */
  1283.         break;
  1284.     }
  1285.     incode = code;
  1286.     /*
  1287.      * Special case for KwKwK string.
  1288.      */
  1289.     if ( code >= free_ent ) {
  1290.             *stackp++ = finchar;
  1291.         code = oldcode;
  1292.     }
  1293.  
  1294.     /*
  1295.      * Generate output characters in reverse order
  1296.      */
  1297. #ifdef SIGNED_COMPARE_SLOW
  1298.     while ( ((unsigned long)code) >= ((unsigned long)256) ) {
  1299. #else
  1300.     while ( code >= 256 ) {
  1301. #endif
  1302.         *stackp++ = tab_suffixof(code);
  1303.         code = tab_prefixof(code);
  1304.     }
  1305.     *stackp++ = finchar = tab_suffixof(code);
  1306.  
  1307.     /*
  1308.      * And put them out in forward order
  1309.      */
  1310.     do
  1311.         putchar ( *--stackp );
  1312.     while ( stackp > de_stack );
  1313.  
  1314.     /*
  1315.      * Generate the new entry.
  1316.      */
  1317.     if ( (code=free_ent) < maxmaxcode ) {
  1318.         tab_prefixof(code) = (unsigned short)oldcode;
  1319.         tab_suffixof(code) = finchar;
  1320.         free_ent = code+1;
  1321.     } 
  1322.     /*
  1323.      * Remember previous code.
  1324.      */
  1325.     oldcode = incode;
  1326.     }
  1327.     fflush( stdout );
  1328.     if(ferror(stdout))
  1329.     writeerr();
  1330. }
  1331.  
  1332. /*****************************************************************
  1333.  * TAG( getcode )
  1334.  *
  1335.  * Read one code from the standard input.  If EOF, return -1.
  1336.  * Inputs:
  1337.  *     stdin
  1338.  * Outputs:
  1339.  *     code or -1 is returned.
  1340.  */
  1341.  
  1342. code_int
  1343. getcode() {
  1344.     /*
  1345.      * On the VAX, it is important to have the register declarations
  1346.      * in exactly the order given, or the asm will break.
  1347.      */
  1348.     register code_int code;
  1349.     static int offset = 0, size = 0;
  1350.     static char_type buf[BITS];
  1351.     register int r_off, bits;
  1352.     register char_type *bp = buf;
  1353.  
  1354.     if ( clear_flg > 0 || offset >= size || free_ent > maxcode ) {
  1355.     /*
  1356.      * If the next entry will be too big for the current code
  1357.      * size, then we must increase the size.  This implies reading
  1358.      * a new buffer full, too.
  1359.      */
  1360.     if ( free_ent > maxcode ) {
  1361.         n_bits++;
  1362.         if ( n_bits == maxbits )
  1363.         maxcode = maxmaxcode;    /* won't get any bigger now */
  1364.         else
  1365.         maxcode = MAXCODE(n_bits);
  1366.     }
  1367.     if ( clear_flg > 0) {
  1368.             maxcode = MAXCODE (n_bits = INIT_BITS);
  1369.         clear_flg = 0;
  1370.     }
  1371.     size = fread( buf, 1, n_bits, stdin );
  1372.     if ( size <= 0 )
  1373.         return -1;            /* end of file */
  1374.     offset = 0;
  1375.     /* Round size down to integral number of codes */
  1376.     size = (size << 3) - (n_bits - 1);
  1377.     }
  1378.     r_off = offset;
  1379.     bits = n_bits;
  1380. #ifdef vax
  1381.     asm( "extzv   r10,r9,(r8),r11" );
  1382. #else /* not a vax */
  1383.     /*
  1384.      * Get to the first byte.
  1385.      */
  1386.     bp += (r_off >> 3);
  1387.     r_off &= 7;
  1388.     /* Get first part (low order bits) */
  1389. #ifdef NO_UCHAR
  1390.     code = ((*bp++ >> r_off) & rmask[8 - r_off]) & 0xff;
  1391. #else
  1392.     code = (*bp++ >> r_off);
  1393. #endif /* NO_UCHAR */
  1394.     bits -= (8 - r_off);
  1395.     r_off = 8 - r_off;        /* now, offset into code word */
  1396.     /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
  1397.     if ( bits >= 8 ) {
  1398. #ifdef NO_UCHAR
  1399.         code |= (*bp++ & 0xff) << r_off;
  1400. #else
  1401.         code |= *bp++ << r_off;
  1402. #endif /* NO_UCHAR */
  1403.         r_off += 8;
  1404.         bits -= 8;
  1405.     }
  1406.     /* high order bits. */
  1407.     code |= (*bp & rmask[bits]) << r_off;
  1408. #endif /* vax */
  1409.     offset += n_bits;
  1410.  
  1411.     return code;
  1412. }
  1413.  
  1414. char *
  1415. rindex(s, c)        /* For those who don't have it in libc.a */
  1416. register char *s, c;
  1417. {
  1418.     char *p;
  1419.     for (p = NULL; *s; s++)
  1420.         if (*s == c)
  1421.         p = s;
  1422.     return(p);
  1423. }
  1424.  
  1425. #ifdef DEBUG
  1426. printcodes()
  1427. {
  1428.     /*
  1429.      * Just print out codes from input file.  For debugging.
  1430.      */
  1431.     code_int code;
  1432.     int col = 0, bits;
  1433.  
  1434.     bits = n_bits = INIT_BITS;
  1435.     maxcode = MAXCODE(n_bits);
  1436.     free_ent = ((block_compress) ? FIRST : 256 );
  1437.     while ( ( code = getcode() ) >= 0 ) {
  1438.     if ( (code == CLEAR) && block_compress ) {
  1439.            free_ent = FIRST - 1;
  1440.            clear_flg = 1;
  1441.     }
  1442.     else if ( free_ent < maxmaxcode )
  1443.         free_ent++;
  1444.     if ( bits != n_bits ) {
  1445.         fprintf(stderr, "\nChange to %d bits\n", n_bits );
  1446.         bits = n_bits;
  1447.         col = 0;
  1448.     }
  1449.     fprintf(stderr, "%5d%c", code, (col+=6) >= 74 ? (col = 0, '\n') : ' ' );
  1450.     }
  1451.     putc( '\n', stderr );
  1452.     exit( 0 );
  1453. }
  1454.  
  1455. code_int sorttab[1<<BITS];    /* sorted pointers into htab */
  1456.  
  1457. dump_tab()    /* dump string table */
  1458. {
  1459.     register int i, first;
  1460.     register ent;
  1461. #define STACK_SIZE    15000
  1462.     int stack_top = STACK_SIZE;
  1463.     register c;
  1464.  
  1465.     if(do_decomp == 0) {    /* compressing */
  1466.     register int flag = 1;
  1467.  
  1468.     for(i=0; i<hsize; i++) {    /* build sort pointers */
  1469.         if((long)htabof(i) >= 0) {
  1470.             sorttab[codetabof(i)] = i;
  1471.         }
  1472.     }
  1473.     first = block_compress ? FIRST : 256;
  1474.     for(i = first; i < free_ent; i++) {
  1475.         fprintf(stderr, "%5d: \"", i);
  1476.         de_stack[--stack_top] = '\n';
  1477.         de_stack[--stack_top] = '"';
  1478.         stack_top = in_stack((htabof(sorttab[i])>>maxbits)&0xff, 
  1479.                                      stack_top);
  1480.         for(ent=htabof(sorttab[i]) & ((1<<maxbits)-1);
  1481.             ent > 256;
  1482.             ent=htabof(sorttab[ent]) & ((1<<maxbits)-1)) {
  1483.             stack_top = in_stack(htabof(sorttab[ent]) >> maxbits,
  1484.                         stack_top);
  1485.         }
  1486.         stack_top = in_stack(ent, stack_top);
  1487.         fwrite( &de_stack[stack_top], 1, STACK_SIZE-stack_top, stderr);
  1488.            stack_top = STACK_SIZE;
  1489.     }
  1490.    } else if(!debug) {    /* decompressing */
  1491.  
  1492.        for ( i = 0; i < free_ent; i++ ) {
  1493.        ent = i;
  1494.        c = tab_suffixof(ent);
  1495.        if ( isascii(c) && isprint(c) )
  1496.            fprintf( stderr, "%5d: %5d/'%c'  \"",
  1497.                ent, tab_prefixof(ent), c );
  1498.        else
  1499.            fprintf( stderr, "%5d: %5d/\\%03o \"",
  1500.                ent, tab_prefixof(ent), c );
  1501.        de_stack[--stack_top] = '\n';
  1502.        de_stack[--stack_top] = '"';
  1503.        for ( ; ent != NULL;
  1504.            ent = (ent >= FIRST ? tab_prefixof(ent) : NULL) ) {
  1505.            stack_top = in_stack(tab_suffixof(ent), stack_top);
  1506.        }
  1507.        fwrite( &de_stack[stack_top], 1, STACK_SIZE - stack_top, stderr );
  1508.        stack_top = STACK_SIZE;
  1509.        }
  1510.     }
  1511. }
  1512.  
  1513. int
  1514. in_stack(c, stack_top)
  1515.     register c, stack_top;
  1516. {
  1517.     if ( (isascii(c) && isprint(c) && c != '\\') || c == ' ' ) {
  1518.         de_stack[--stack_top] = c;
  1519.     } else {
  1520.         switch( c ) {
  1521.         case '\n': de_stack[--stack_top] = 'n'; break;
  1522.         case '\t': de_stack[--stack_top] = 't'; break;
  1523.         case '\b': de_stack[--stack_top] = 'b'; break;
  1524.         case '\f': de_stack[--stack_top] = 'f'; break;
  1525.         case '\r': de_stack[--stack_top] = 'r'; break;
  1526.         case '\\': de_stack[--stack_top] = '\\'; break;
  1527.         default:
  1528.          de_stack[--stack_top] = '0' + c % 8;
  1529.          de_stack[--stack_top] = '0' + (c / 8) % 8;
  1530.          de_stack[--stack_top] = '0' + c / 64;
  1531.          break;
  1532.         }
  1533.         de_stack[--stack_top] = '\\';
  1534.     }
  1535.     return stack_top;
  1536. }
  1537. #endif /* DEBUG */
  1538.  
  1539. writeerr()
  1540. {
  1541.     perror ( ofname );
  1542.     unlink ( ofname );
  1543.     exit ( 1 );
  1544. }
  1545.  
  1546. copystat(ifname, ofname)
  1547. char *ifname, *ofname;
  1548. {
  1549.     struct stat statbuf;
  1550.     int mode;
  1551.     time_t timep[2];
  1552.  
  1553.     fclose(stdout);
  1554.     if (stat(ifname, &statbuf)) {        /* Get stat on input file */
  1555.     perror(ifname);
  1556.     return;
  1557.     }
  1558.     if ((statbuf.st_mode & S_IFMT/*0170000*/) != S_IFREG/*0100000*/) {
  1559.     if(quiet)
  1560.             fprintf(stderr, "%s: ", ifname);
  1561.     fprintf(stderr, " -- not a regular file: unchanged");
  1562.     exit_stat = 1;
  1563.     } else if (statbuf.st_nlink > 1) {
  1564.     if(quiet)
  1565.             fprintf(stderr, "%s: ", ifname);
  1566.     fprintf(stderr, " -- has %d other links: unchanged",
  1567.         statbuf.st_nlink - 1);
  1568.     exit_stat = 1;
  1569.     } else if (exit_stat == 2 && (!force)) { /* No compression: remove file.Z */
  1570.     if(!quiet)
  1571.         fprintf(stderr, " -- file unchanged");
  1572.     } else {            /* ***** Successful Compression ***** */
  1573.     exit_stat = 0;
  1574.     mode = statbuf.st_mode & 07777;
  1575.     if (chmod(ofname, mode))        /* Copy modes */
  1576.         perror(ofname);
  1577.     chown(ofname, statbuf.st_uid, statbuf.st_gid);    /* Copy ownership */
  1578.     timep[0] = statbuf.st_atime;
  1579.     timep[1] = statbuf.st_mtime;
  1580.     utime(ofname, timep);    /* Update last accessed and modified times */
  1581.     if (unlink(ifname))    /* Remove input file */
  1582.         perror(ifname);
  1583.     if(!quiet)
  1584.         fprintf(stderr, " -- replaced with %s", ofname);
  1585.     return;        /* Successful return */
  1586.     }
  1587.  
  1588.     /* Unsuccessful return -- one of the tests failed */
  1589.     if (unlink(ofname))
  1590.     perror(ofname);
  1591. }
  1592. /*
  1593.  * This routine returns 1 if we are running in the foreground and stderr
  1594.  * is a tty.
  1595.  */
  1596. foreground()
  1597. {
  1598.     if(bgnd_flag) {    /* background? */
  1599.         return(0);
  1600.     } else {            /* foreground */
  1601.         if(isatty(2)) {        /* and stderr is a tty */
  1602.             return(1);
  1603.         } else {
  1604.             return(0);
  1605.         }
  1606.     }
  1607. }
  1608.  
  1609. onintr ( )
  1610. {
  1611.     unlink ( ofname );
  1612.     exit ( 1 );
  1613. }
  1614.  
  1615. oops ( )    /* wild pointer -- assume bad input */
  1616. {
  1617.     if ( do_decomp == 1 ) 
  1618.         fprintf ( stderr, "uncompress: corrupt input\n" );
  1619.     unlink ( ofname );
  1620.     exit ( 1 );
  1621. }
  1622.  
  1623. cl_block ()        /* table clear for block compress */
  1624. {
  1625.     register long int rat;
  1626.  
  1627.     checkpoint = in_count + CHECK_GAP;
  1628. #ifdef DEBUG
  1629.     if ( debug ) {
  1630.             fprintf ( stderr, "count: %ld, ratio: ", in_count );
  1631.              prratio ( stderr, in_count, bytes_out );
  1632.         fprintf ( stderr, "\n");
  1633.     }
  1634. #endif /* DEBUG */
  1635.  
  1636.     if(in_count > 0x007fffff) {    /* shift will overflow */
  1637.     rat = bytes_out >> 8;
  1638.     if(rat == 0) {        /* Don't divide by zero */
  1639.         rat = 0x7fffffff;
  1640.     } else {
  1641.         rat = in_count / rat;
  1642.     }
  1643.     } else {
  1644.     rat = (in_count << 8) / bytes_out;    /* 8 fractional bits */
  1645.     }
  1646.     if ( rat > ratio ) {
  1647.     ratio = rat;
  1648.     } else {
  1649.     ratio = 0;
  1650. #ifdef DEBUG
  1651.     if(verbose)
  1652.         dump_tab();    /* dump string table */
  1653. #endif
  1654.      cl_hash ( (count_int) hsize );
  1655.     free_ent = FIRST;
  1656.     clear_flg = 1;
  1657.     output ( (code_int) CLEAR );
  1658. #ifdef DEBUG
  1659.     if(debug)
  1660.             fprintf ( stderr, "clear\n" );
  1661. #endif /* DEBUG */
  1662.     }
  1663. }
  1664.  
  1665. cl_hash(hsize)        /* reset code table */
  1666.     register count_int hsize;
  1667. {
  1668. #ifndef XENIX_16    /* Normal machine */
  1669.     register count_int *htab_p = htab+hsize;
  1670. #else
  1671.     register j;
  1672.     register long k = hsize;
  1673.     register count_int *htab_p;
  1674. #endif
  1675.     register long i;
  1676.     register long m1 = -1;
  1677.  
  1678. #ifdef XENIX_16
  1679.     for(j=0; j<=8 && k>=0; j++,k-=8192) {
  1680.     i = 8192;
  1681.     if(k < 8192) {
  1682.         i = k;
  1683.     }
  1684.     htab_p = &(htab[j][i]);
  1685.     i -= 16;
  1686.     if(i > 0) {
  1687. #else
  1688.     i = hsize - 16;
  1689. #endif
  1690.      do {                /* might use Sys V memset(3) here */
  1691.         *(htab_p-16) = m1;
  1692.         *(htab_p-15) = m1;
  1693.         *(htab_p-14) = m1;
  1694.         *(htab_p-13) = m1;
  1695.         *(htab_p-12) = m1;
  1696.         *(htab_p-11) = m1;
  1697.         *(htab_p-10) = m1;
  1698.         *(htab_p-9) = m1;
  1699.         *(htab_p-8) = m1;
  1700.         *(htab_p-7) = m1;
  1701.         *(htab_p-6) = m1;
  1702.         *(htab_p-5) = m1;
  1703.         *(htab_p-4) = m1;
  1704.         *(htab_p-3) = m1;
  1705.         *(htab_p-2) = m1;
  1706.         *(htab_p-1) = m1;
  1707.         htab_p -= 16;
  1708.     } while ((i -= 16) >= 0);
  1709. #ifdef XENIX_16
  1710.     }
  1711.     }
  1712. #endif
  1713.         for ( i += 16; i > 0; i-- )
  1714.         *--htab_p = m1;
  1715. }
  1716.  
  1717. prratio(stream, num, den)
  1718. XFILE *stream;
  1719. long int num, den;
  1720. {
  1721.     register int q;            /* Doesn't need to be long */
  1722.  
  1723.     if(num > 214748L) {        /* 2147483647/10000 */
  1724.         q = num / (den / 10000L);
  1725.     } else {
  1726.         q = 10000L * num / den;        /* Long calculations, though */
  1727.     }
  1728.     if (q < 0) {
  1729.         putc('-', stream);
  1730.         q = -q;
  1731.     }
  1732.     fprintf(stream, "%d.%02d%%", q / 100, q % 100);
  1733. }
  1734.  
  1735. version()
  1736. {
  1737.     fprintf(stderr, "%s\n", rcs_ident);
  1738.     fprintf(stderr, "Options: ");
  1739. #ifdef vax
  1740.     fprintf(stderr, "vax, ");
  1741. #endif
  1742. #ifdef NO_UCHAR
  1743.     fprintf(stderr, "NO_UCHAR, ");
  1744. #endif
  1745. #ifdef SIGNED_COMPARE_SLOW
  1746.     fprintf(stderr, "SIGNED_COMPARE_SLOW, ");
  1747. #endif
  1748. #ifdef XENIX_16
  1749.     fprintf(stderr, "XENIX_16, ");
  1750. #endif
  1751. #ifdef COMPATIBLE
  1752.     fprintf(stderr, "COMPATIBLE, ");
  1753. #endif
  1754. #ifdef DEBUG
  1755.     fprintf(stderr, "DEBUG, ");
  1756. #endif
  1757. #ifdef BSD4_2
  1758.     fprintf(stderr, "BSD4_2, ");
  1759. #endif
  1760.     fprintf(stderr, "BITS = %d\n", BITS);
  1761. }
  1762. SHAR_EOF
  1763. if test 39614 -ne "`wc -c < 'compress.c'`"
  1764. then
  1765.     echo shar: error transmitting "'compress.c'" '(should have been 39614 characters)'
  1766. fi
  1767. fi # end of overwriting check
  1768. echo shar: extracting "'Makefile'" '(1435 characters)'
  1769. if test -f 'Makefile'
  1770. then
  1771.     echo shar: will not over-write existing file "'Makefile'"
  1772. else
  1773. sed 's/^X//' << \SHAR_EOF > 'Makefile'
  1774. CC=cc
  1775. COMFLAGS=-O
  1776. BIN=/usr/bin
  1777. MAN=/usr/man/man1
  1778. #define to "l" if manuals go on /usr/man/manl
  1779. L=1
  1780.  
  1781. all :    compress atob btoa
  1782.  
  1783. compress : compress.c USERMEM
  1784.     $(CC) $(COMFLAGS) -DUSERMEM=`cat USERMEM` -o compress compress.c
  1785.  
  1786. # USERMEM may have to be set by hand.  It should contain the amount of
  1787. # available user memory in bytes.  See the README file for more info.
  1788. USERMEM:
  1789.     sh usermem > USERMEM
  1790.  
  1791. atob:    atob.c
  1792.     $(CC) $(COMFLAGS) -o atob atob.c
  1793.  
  1794. btoa:    btoa.c
  1795.     $(CC) $(COMFLAGS) -o btoa btoa.c
  1796.  
  1797. install: compress atob btoa zmore zcmp zdiff compressdir uncompressdir btoa.1 compress.1 compressdir.1 zmore.1 zcmp.1 tarmail untarmail
  1798.     cp compress $(BIN)
  1799.     rm -f $(BIN)/uncompress $(BIN)/zcat
  1800.     ln $(BIN)/compress $(BIN)/uncompress
  1801.     ln $(BIN)/compress $(BIN)/zcat
  1802.     cp zmore zcmp zdiff compressdir uncompressdir $(BIN)
  1803.     cp atob btoa tarmail untarmail $(BIN)
  1804.     cp btoa.1 $(MAN)/btoa.$(L)
  1805.     rm -f $(MAN)/atob.$(L) $(MAN)/tarmail.$(L) $(MAN)/untarmail.$(L)
  1806.     ln $(MAN)/btoa.$(L) $(MAN)/atob.$(L)
  1807.     ln $(MAN)/btoa.$(L) $(MAN)/tarmail.$(L)
  1808.     ln $(MAN)/btoa.$(L) $(MAN)/untarmail.$(L)
  1809.     cp compress.1 $(MAN)/compress.$(L)
  1810.     rm -f $(MAN)/uncompress.$(L) $(MAN)/zcat.$(L)
  1811.     ln $(MAN)/compress.$(L) $(MAN)/uncompress.$(L)
  1812.     ln $(MAN)/compress.$(L) $(MAN)/zcat.$(L)
  1813.     cp compressdir.1 $(MAN)/compressdir.$(L)
  1814.     cp zmore.1 $(MAN)/zmore.$(L)
  1815.     cp zcmp.1 $(MAN)/zcmp.$(L)
  1816.     rm -f $(MAN)/zdiff.$(L)
  1817.     ln $(MAN)/zcmp.$(L) $(MAN)/zdiff.$(L)
  1818.  
  1819. clean:
  1820.     rm -f compress atob btoa
  1821. SHAR_EOF
  1822. if test 1435 -ne "`wc -c < 'Makefile'`"
  1823. then
  1824.     echo shar: error transmitting "'Makefile'" '(should have been 1435 characters)'
  1825. fi
  1826. fi # end of overwriting check
  1827. echo shar: extracting "'usermem'" '(1748 characters)'
  1828. if test -f 'usermem'
  1829. then
  1830.     echo shar: will not over-write existing file "'usermem'"
  1831. else
  1832. sed 's/^X//' << \SHAR_EOF > 'usermem'
  1833. : This shell script snoops around to find the maximum amount of available
  1834. : user memory.  These variables need to be set only if there is no
  1835. : /usr/adm/messages.  KMEM, UNIX, and CLICKSIZE can be set on the command
  1836. : line, if desired, e.g. UNIX=/unix
  1837. KMEM=/dev/kmem        # User needs read access to KMEM
  1838. UNIX=
  1839. # VAX            CLICKSIZE=512,    UNIX=/vmunix
  1840. # PDP-11        CLICKSIZE=64,    UNIX=/unix
  1841. # CADLINC 68000        CLICKSIZE=4096,    UNIX=/unix
  1842. # Perkin-Elmer 3205    CLICKSIZE=4096,    UNIX=/edition7
  1843. # Perkin-Elmer all others, CLICKSIZE=2048, UNIX=/edition7
  1844. CLICKSIZE=512
  1845. eval $*
  1846.  
  1847. XSIZE=0
  1848. if test -r /usr/adm/messages    # probably the most transportable
  1849. then
  1850.     SIZE=`grep avail /usr/adm/messages | sed -n '$s/.*[     ]//p'`
  1851. fi
  1852.  
  1853. if test 0$SIZE -le 0        # no SIZE in /usr/adm/messages
  1854. then
  1855.     if test -r $KMEM        # Readable KMEM
  1856.     then
  1857.     if test -n "$UNIX"
  1858.     then
  1859.         : User must have specified it already.
  1860.     elif test -r /vmunix
  1861.     then
  1862.         UNIX=/vmunix
  1863.         CLICKSIZE=512    # Probably VAX
  1864.     elif test -r /edition7
  1865.     then
  1866.         UNIX=/edition7
  1867.         CLICKSIZE=2048    # Perkin-Elmer: change to 4096 on a 3205
  1868.     elif test -r /unix
  1869.     then
  1870.         UNIX=/unix        # Could be anything
  1871.     fi
  1872.     if test -n "$UNIX"
  1873.     then
  1874.         SIZE=`echo maxmem/D | adb $UNIX $KMEM | sed -n '$s/.*[     ]//p'`
  1875.         if test 0$SIZE -le 0
  1876.         then
  1877.         SIZE=`echo physmem/D | adb $UNIX $KMEM | sed -n '$s/.*[     ]//p'`
  1878.         fi
  1879.         SIZE=`expr 0$SIZE '*' $CLICKSIZE`
  1880.     fi
  1881.     fi
  1882. fi
  1883.  
  1884. case $UNIX in
  1885.     /vmunix)        # Assume 4.2bsd: check for resource limits
  1886.     MAXSIZE=`csh -c limit | awk 'BEGIN    { MAXSIZE = 1000000 }
  1887. /datasize|memoryuse/ && NF == 3    { if ($2 < MAXSIZE) MAXSIZE = $2 }
  1888. END    { print MAXSIZE * 1000 }'`
  1889.     if test $MAXSIZE -lt $SIZE
  1890.     then
  1891.         SIZE=$MAXSIZE
  1892.     fi
  1893.     ;;
  1894. esac
  1895.  
  1896. if test 0$SIZE -le 0
  1897. then
  1898.     echo 0;exit 1
  1899. else
  1900.     echo $SIZE
  1901. fi
  1902. SHAR_EOF
  1903. if test 1748 -ne "`wc -c < 'usermem'`"
  1904. then
  1905.     echo shar: error transmitting "'usermem'" '(should have been 1748 characters)'
  1906. fi
  1907. chmod +x 'usermem'
  1908. fi # end of overwriting check
  1909. #    End of shell archive
  1910. exit 0
  1911.